package com.tepth.busfix.ic.template;

import cc.lotuscard.LotusCardDriver;
import cc.lotuscard.LotusCardParam;

/**
 * Created by zhangyu on 2017/9/29.
 */

public abstract class DeviceOperation {
    public abstract void errorMsg(String msg);

    public abstract void succeedMsg(String msg);

    public abstract void readCompleteData(byte[] finalData);

    private LotusCardDriver mLotusCardDriver;
    private boolean mCancel = false;
    private Number mDeviceHandle;
    private long mHandle = -1;

    public void error(String s) {
        if (!mCancel) {
            errorMsg(s);
        }
    }

    public void succeed(String s) {
        if (!mCancel) {
            succeedMsg(s);
        }
    }

    public void readComplete(byte[] finalData) {
        if (!mCancel) {
            readCompleteData(finalData);
        }
    }

    public final void operationDevice(LotusCardDriver lotusCardDriver) {
        mCancel = false;
        mLotusCardDriver = lotusCardDriver;
        new Thread(new Runnable() {
            @Override
            public void run() {
                startOperation2();
            }
        }).start();
    }

    private void startOperation2() {
        LotusCardParam tLotusCardParam1 = new LotusCardParam();
        //打开设备
        mHandle = mLotusCardDriver.OpenDevice("", 0, 0, 0, 0,// 使用内部默认超时设置
                true);
        if (mHandle == -1) {
            error("设备打开失败!");
        } else {
            if (!mLotusCardDriver.Beep(mHandle, 10)) {
                error("蜂鸣器唤醒失败!");
            } else {
                succeed("蜂鸣器唤醒成功,正在读取卡号...");

                int nRequestType = LotusCardDriver.RT_NOT_HALT;
                if (!mLotusCardDriver.GetCardNo(mHandle, nRequestType,
                        tLotusCardParam1)) {
                    error("卡号读取失败!");
                } else {
                    succeed("卡号读取成功,正在加载密钥...");
                    tLotusCardParam1.arrKeys[0] = (byte) 0xff;
                    tLotusCardParam1.arrKeys[1] = (byte) 0xff;
                    tLotusCardParam1.arrKeys[2] = (byte) 0xff;
                    tLotusCardParam1.arrKeys[3] = (byte) 0xff;
                    tLotusCardParam1.arrKeys[4] = (byte) 0xff;
                    tLotusCardParam1.arrKeys[5] = (byte) 0xff;
                    tLotusCardParam1.nKeysSize = 6;

                    if (!mLotusCardDriver.LoadKey(mHandle, LotusCardDriver.AM_A,
                            1, tLotusCardParam1)) {
                        error("密钥加载失败!");
                    } else {
                        succeed("密钥加载成功,正在认证...");
                        if (!mLotusCardDriver.Authentication(mHandle,
                                LotusCardDriver.AM_A, 1, tLotusCardParam1)) {
                            error("认证失败!");
                        } else {
                            succeed("认证成功,正在读取卡片信息...");
                            byte[] data = new byte[48];
                            for (int i = 0; i < 3; i++) {
                                if (!mLotusCardDriver.Read(mHandle, 4 + i, tLotusCardParam1)) {
                                    error("信息块" + (4 + i) + "读取失败!");
                                } else {
                                    succeed("信息读取成功!正在解析...");
                                }
                                int j = i * 16;
                                for (int k = 0; k < 16; k++) {
                                    data[j++] = tLotusCardParam1.arrBuffer[k];
                                }
                                if (i >= 2) {
                                    int len = 0;
                                    for (int m = data.length - 1; m >= 0; m--) {
                                        if (data[m] != 0) {
                                            len = m;
                                            break;
                                        }
                                    }
                                    final byte[] finalData = new byte[len + 1];
                                    System.arraycopy(data, 0, finalData, 0, finalData.length);
                                    succeed("数据解析成功!");
                                    if (mHandle != -1) {
                                        cancel();
                                    }
                                    readComplete(finalData);
                                }
                            }
                        }
                    }

                }

            }
        }
    }

    private void startOperation() {
        LotusCardParam tLotusCardParam1 = new LotusCardParam();
        //打开设备
        mDeviceHandle = new Number(-1);
        Number count = new Number(0);
        openDevice(mDeviceHandle);
        succeed("设备打开成功!");
        //唤起蜂鸣器
        callBeep(mDeviceHandle.count, false, count);
        //获取卡号
        int nRequestType = LotusCardDriver.RT_NOT_HALT;
        getCarNumber(mDeviceHandle.count, nRequestType, tLotusCardParam1, false, count);
        //加载密钥
        tLotusCardParam1.arrKeys[0] = (byte) 0xff;
        tLotusCardParam1.arrKeys[1] = (byte) 0xff;
        tLotusCardParam1.arrKeys[2] = (byte) 0xff;
        tLotusCardParam1.arrKeys[3] = (byte) 0xff;
        tLotusCardParam1.arrKeys[4] = (byte) 0xff;
        tLotusCardParam1.arrKeys[5] = (byte) 0xff;
        tLotusCardParam1.nKeysSize = 6;
        loadKey(mDeviceHandle.count, tLotusCardParam1, false, count);
        //密钥认证
        authentication(mDeviceHandle.count, tLotusCardParam1, false, count);
        //读卡信息
        read(mDeviceHandle.count, tLotusCardParam1, false, count);
    }

    private void openDevice(Number number) {
        if (number.count == -1 && !mCancel) {
            try {
                number.count = mLotusCardDriver.OpenDevice("", 0, 0, 0, 0,// 使用内部默认超时设置
                        true);
                succeed("正在打开设备...");
                Thread.sleep(500);
                openDevice(number);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void callBeep(long deviceHandle, boolean isSucceed, Number number) {
        if (!isSucceed && !mCancel) {
            if (number.increase() < 5) {
                try {
                    succeed("唤醒蜂鸣器第" + number.count + "次!deviceHandle:" + deviceHandle);
                    isSucceed = mLotusCardDriver.Beep(deviceHandle, 10);
                    Thread.sleep(100);
                    callBeep(deviceHandle, isSucceed, number);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                //  error(deviceHandle, "蜂鸣器唤醒失败!");
                mCancel = true;
            }
        } else {
            number.restore();
        }

    }

    private void getCarNumber(long deviceHandle, int nRequestType,
                              LotusCardParam tLotusCardParam1,
                              boolean isSucceed, Number count) {
        if (!isSucceed && !mCancel) {
            if (count.increase() < 5) {
                try {
                    succeed("读取卡号第" + count.count + "次!");
                    getCarNumber(deviceHandle, nRequestType, tLotusCardParam1, mLotusCardDriver.GetCardNo(deviceHandle, nRequestType,
                            tLotusCardParam1), count);
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                //  error(deviceHandle, "卡号读取失败!");
                mCancel = true;
            }
        } else {
            count.restore();
        }

    }

    private void loadKey(long deviceHandle, LotusCardParam tLotusCardParam1
            , boolean isSucceed, Number count) {
        if (!isSucceed && !mCancel) {
            if (count.increase() < 5) {
                try {
                    succeed("加载密钥第" + count.count + "次!");
                    loadKey(deviceHandle,
                            tLotusCardParam1,
                            mLotusCardDriver.LoadKey(deviceHandle, LotusCardDriver.AM_A,
                                    1, tLotusCardParam1), count);
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                // error(deviceHandle, "密钥加载失败!");
                mCancel = true;
            }
        } else {
            count.restore();
        }
    }

    private void authentication(long deviceHandle, LotusCardParam tLotusCardParam1,
                                boolean isSucceed, Number count) {
        if (!isSucceed && !mCancel) {
            if (count.increase() < 5) {
                try {
                    succeed("认证密钥第" + count.count + "次!");
                    authentication(deviceHandle,
                            tLotusCardParam1,
                            mLotusCardDriver.Authentication(deviceHandle,
                                    LotusCardDriver.AM_A, 1, tLotusCardParam1), count);
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                //   error(deviceHandle, "认证失败!");
                mCancel = true;
            }
        } else {
            count.restore();
        }
    }

    private void read(long deviceHandle,
                      LotusCardParam tLotusCardParam1,
                      boolean isSucceed,
                      Number count) {
        if (!isSucceed && !mCancel) {
            if (count.increase() < 5) {
                try {
                    succeed("读取数据第" + count.count + "次!");
                    read(deviceHandle, tLotusCardParam1, readCard(deviceHandle, tLotusCardParam1), count);
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                //     error(deviceHandle, "数据读取失败!");
                mCancel = true;
            }
        } else {
            count.restore();
        }
    }

    private boolean readCard(long deviceHandle,
                             LotusCardParam tLotusCardParam1) {
        byte[] data = new byte[48];
        for (int i = 0; i < 3; i++) {
            if (!mLotusCardDriver.Read(deviceHandle, 4 + i, tLotusCardParam1)) {
                return false;
            }
            int j = i * 16;
            for (int k = 0; k < 16; k++) {
                data[j++] = tLotusCardParam1.arrBuffer[k];
            }
            if (i >= 2) {
                int len = 0;
                for (int m = data.length - 1; m >= 0; m--) {
                    if (data[m] != 0) {
                        len = m;
                        break;
                    }
                }
                final byte[] finalData = new byte[len + 1];
                System.arraycopy(data, 0, finalData, 0, finalData.length);
                succeed("数据解析成功!");
                if (deviceHandle != -1) {
                    cancel();
                }
                readComplete(finalData);
                return true;
            }
        }
        return false;
    }


    public void cancel() {
        mCancel = true;
        if (mHandle != -1) {
            mLotusCardDriver.CloseDevice(mHandle);
            mHandle = -1;
        }
    }

    private class Number {
        long count;

        Number(long count) {
            this.count = count;
        }

        long decrease() {
            return count--;

        }

        long increase() {
            return count++;
        }

        void restore() {
            count = 0;
        }
    }
}
